package com.kzw.core.util;

import java.io.OutputStream;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Workbook;

import com.lowagie.text.Document;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;


/**
 * 导出excel与pdf工具类<br>
 * 增加：设置行高、单元格宽度
 */
public class ExportUtil {
	
	/**
	 * 导出excel，优化版
	 * @param list 要导出的数据
	 * @param os 输出流
	 * @param coiId 列名
	 * @param colName 属性名
	 */
	public static void ExportXls(List<Object> list, OutputStream os, String colId, String colName){

		//2003版本  
		Workbook wb = new HSSFWorkbook();
		HSSFSheet sheet1=(HSSFSheet) wb.createSheet("sheet1");
		
		HSSFRow row=sheet1.createRow(0);
		row.setHeightInPoints(30); //行高
		HSSFCell cell=null;
		CellStyle style = wb.createCellStyle();
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);	//水平居中
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); //垂直居中	
		style.setWrapText(true); //自动换行		
		org.apache.poi.ss.usermodel.Font font = wb.createFont();
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); 
		style.setFont(font); //加粗
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN); 	//下边框
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);		//左边框
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);		//上边框
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);	//右边框
		
		
		// 设置最长的宽度（最长300像素/42）
		List<int[]> widths = new ArrayList<int[]>();
		String[] cName = colName.split(",");
		for(int index=0; index<cName.length; index++){
			cell = row.createCell(index);
			cell.setCellStyle(style);
			cell.setCellValue(cName[index]);			
			widths.add(index, new int[] {index, cName[index].getBytes().length});
		}
		
		try {			
			style = wb.createCellStyle();
			style.setAlignment(HSSFCellStyle.ALIGN_CENTER);	//水平居中
			style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); //垂直居中	
			style.setWrapText(true); //自动换行
			font = wb.createFont();
			font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); 
			style.setFont(font);
			style.setBorderBottom(HSSFCellStyle.BORDER_THIN); 	//下边框
			style.setBorderLeft(HSSFCellStyle.BORDER_THIN);		//左边框
			style.setBorderTop(HSSFCellStyle.BORDER_THIN);		//上边框
			style.setBorderRight(HSSFCellStyle.BORDER_THIN);	//右边框
			
			if(list!=null&&list.size()>0) {	
				String value = "";
				int cnt = list.size();
				List<Object> methods = findMethodByCids(colId, list.get(0));
				for(int indexList=0; indexList<cnt; indexList++) {
					row = sheet1.createRow((short)indexList+1);
					row.setHeightInPoints(20);
					Object obj = list.get(indexList);
					int index = 0;
					for(Object md : methods) {
						value = invokeCell(obj, md);
						cell=row.createCell(index);
						cell.setCellStyle(style);
						cell.setCellValue(value);
						
						int[] arr = widths.get(index);
						int w = value.getBytes().length;
						if(w > arr[1]) {
							arr[1] = w;
						}
						
						index++;
					}
				}
			}
			// 设置单元格的宽度
			for(int i=0; i<widths.size(); i++) {
				int arr[] = widths.get(i);
				arr[1] = arr[1]>40 ? 40 : arr[1];
				sheet1.setColumnWidth(i, (arr[1]+2) * 256);
			}
			wb.write(os);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 通过反应调用对象方法
	 * */
	private static String invokeCell(Object obj, Object method) throws Exception {
		String value = "";
		if(method != null){
			if(method.getClass() == Method.class) {
				Method md = (Method)method;
				String typeName = md.getReturnType().getName();
				if(typeName.indexOf("Date")!=-1){
					SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					value = f.format(md.invoke(obj));
				} else {
					value = String.valueOf(md.invoke(obj));
				}
			} else {
				//如果是关联属性的方法
				String[] methodStr = (String[])method;
				Method md = obj.getClass().getMethod(methodStr[0]);
				if(md != null) {
					//获得关联属性（递归）
					Object subObj = md.invoke(obj);
					if(subObj == null) return "";
					
					md = subObj.getClass().getMethod(methodStr[1]);
					if(methodStr.length == 3) {
						subObj = md.invoke(subObj);
						md = subObj.getClass().getMethod(methodStr[2]);
					}
					
					String typeName = md.getReturnType().getName();
					if(typeName.indexOf("Date")!=-1){
						SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						value = f.format(md.invoke(subObj));
					} else {
						value = String.valueOf(md.invoke(subObj));
					}
				}
			}
		}
		if(value==null || value.equals("null")) 
			value = "";
		return value;
	}
	
	/**
	 * 根据cids获得Object对象对应的method
	 * 返回值：Method对象或者String对象
	 * */
	private static List<Object> findMethodByCids(String colId, Object obj) throws Exception {
		String[] cids = colId.split(",");
		List<Object> methods = new ArrayList<Object>(cids.length);
		for(String cid : cids) {
			if(cid.indexOf("javaRenderer") >= 0) {
				cid = cid.replace("javaRenderer", "");
				Method mtd = obj.getClass().getMethod(cid);
				methods.add(mtd);
				continue;
			}
			if(cid.contains(".")) {
				// 存在对象导航, 只考虑两级关系
				String strs[] = cid.split("\\."); 
				if(strs.length == 2) {
					String[] methodStr = new String[2];
					methodStr[0] = "get"+StringUtils.capitalize(strs[0]);
					methodStr[1] = "get"+StringUtils.capitalize(strs[1]);
					methods.add(methodStr);
				} else if(strs.length == 3) {
					String[] methodStr = new String[3];
					methodStr[0] = "get"+StringUtils.capitalize(strs[0]);
					methodStr[1] = "get"+StringUtils.capitalize(strs[1]);
					methodStr[2] = "get"+StringUtils.capitalize(strs[2]);
					methods.add(methodStr);
				}
			} else {
				String methodStr = "get"+ StringUtils.capitalize(cid);
				Method mtd = obj.getClass().getMethod(methodStr);
				methods.add(mtd);
			}
		}
		return methods;
	}
	
	/**
	 * 导出pdf<br>
	 */
	public static void ExportPdf(List<Object> list, OutputStream os, String colId, String colName){
		
		// 设置页面横置
		Rectangle rectPage = new Rectangle(PageSize.A4);
		rectPage = rectPage.rotate();
		// 创建document对象并指定边距
		Document document = new Document(rectPage, 50, 50, 50, 50);
		
		try {
			PdfWriter.getInstance(document, os);
			document.open();
			BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
			Font font = new Font(bfChinese, 8, Font.BOLD);
			
			String[] cid = colId.split(",");
			String[] cname = colName.split(",");
			PdfPTable table = new PdfPTable(cid.length);
			table.setWidthPercentage(100);
			table.setHorizontalAlignment(PdfPTable.ALIGN_LEFT);
			PdfPCell cell = new PdfPCell();
			//设置颜色
			//cell.setBackgroundColor(new Color(213, 141, 69));
			cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
			//设置列名
			for(int index=0;index<cname.length;index++){
				cell.setPhrase(new Paragraph(cname[index], font));
				table.addCell(cell);
			}
			font = new Font(bfChinese, 8, Font.NORMAL);
			
			if(list!=null&&list.size()>0) {
				String value = "";
				int cnt = list.size();
				List<Object> methods = findMethodByCids(colId, list.get(0));
				for(int indexList = 0; indexList < cnt; indexList++){
					Object obj = list.get(indexList);
					for(Object md : methods) {
						value = invokeCell(obj, md);
						cell.setPhrase(new Paragraph(value, font));
						table.addCell(cell);
					}
				}
			}
			document.add(table);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			document.close();
		}
		
	}
}
